﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using RotovapPlatform.Domain.Equipment.Interfaces.Base;

namespace RotovapPlatform.Domain.Equipment.Device.IO
{
	/// <summary>
	/// IO信号管理器
	/// </summary>
	public class IOSignalManager : IIOSignalManager
	{
		private readonly ILogger<IOSignalManager> _logger;
		private readonly ConcurrentDictionary<string, DISignal> _diSignals = new();
		private readonly ConcurrentDictionary<string, DOSignal> _doSignals = new();
		private readonly ConcurrentDictionary<string, AISignal> _aiSignals = new();

		/// <summary>
		/// 获取所有DI信号
		/// </summary>
		public IReadOnlyDictionary<string, IDISignal> DISignals => _diSignals.ToDictionary(x => x.Key, x => (IDISignal)x.Value);

		/// <summary>
		/// 获取所有DO信号
		/// </summary>
		public IReadOnlyDictionary<string, IDOSignal> DOSignals => _doSignals.ToDictionary(x => x.Key, x => (IDOSignal)x.Value);

		/// <summary>
		/// 获取所有AI信号
		/// </summary>
		public IReadOnlyDictionary<string, IAISignal> AISignals => _aiSignals.ToDictionary(x => x.Key, x => (IAISignal)x.Value);

		/// <summary>
		/// 信号状态变化事件
		/// </summary>
		public event EventHandler<IOSignalStateChangedEventArgs> SignalStateChanged;

		/// <summary>
		/// 构造函数
		/// </summary>
		public IOSignalManager(ILogger<IOSignalManager> logger)
		{
			_logger = logger ?? throw new ArgumentNullException(nameof(logger));
		}

		/// <summary>
		/// 获取DI信号
		/// </summary>
		public IDISignal GetDISignal(DISignalId id)
		{
			string signalId = IOSignalUtils.GetDISignalName(id);
			if (_diSignals.TryGetValue(signalId, out var signal))
			{
				return signal;
			}

			_logger.LogWarning($"未找到DI信号: {id}");
			return null;
		}

		/// <summary>
		/// 获取DO信号
		/// </summary>
		public IDOSignal GetDOSignal(DOSignalId id)
		{
			string signalId = IOSignalUtils.GetDOSignalName(id);
			if (_doSignals.TryGetValue(signalId, out var signal))
			{
				return signal;
			}

			_logger.LogWarning($"未找到DO信号: {id}");
			return null;
		}

		/// <summary>
		/// 获取AI信号
		/// </summary>
		public IAISignal GetAISignal(AISignalId id)
		{
			string signalId = IOSignalUtils.GetAISignalName(id);
			if (_aiSignals.TryGetValue(signalId, out var signal))
			{
				return signal;
			}

			_logger.LogWarning($"未找到AI信号: {id}");
			return null;
		}

		/// <summary>
		/// 注册DI信号
		/// </summary>
		public void RegisterDISignal(DISignal signal)
		{
			if (signal == null) throw new ArgumentNullException(nameof(signal));

			// 添加状态变化事件
			signal.StateChanged += OnSignalStateChanged;

			if (_diSignals.TryAdd(signal.Id, signal))
			{
				_logger.LogInformation($"已注册DI信号: {signal.Name}");
			}
			else
			{
				_logger.LogWarning($"DI信号 {signal.Name} 已存在，无法重复注册");
			}
		}

		/// <summary>
		/// 注册DO信号
		/// </summary>
		public void RegisterDOSignal(DOSignal signal)
		{
			if (signal == null) throw new ArgumentNullException(nameof(signal));

			// 添加状态变化事件
			signal.StateChanged += OnSignalStateChanged;

			if (_doSignals.TryAdd(signal.Id, signal))
			{
				_logger.LogInformation($"已注册DO信号: {signal.Name}");
			}
			else
			{
				_logger.LogWarning($"DO信号 {signal.Name} 已存在，无法重复注册");
			}
		}

		/// <summary>
		/// 注册AI信号
		/// </summary>
		public void RegisterAISignal(AISignal signal)
		{
			if (signal == null) throw new ArgumentNullException(nameof(signal));

			// 添加状态变化事件
			signal.StateChanged += OnSignalStateChanged;

			if (_aiSignals.TryAdd(signal.Id, signal))
			{
				_logger.LogInformation($"已注册AI信号: {signal.Name}");
			}
			else
			{
				_logger.LogWarning($"AI信号 {signal.Name} 已存在，无法重复注册");
			}
		}

		/// <summary>
		/// 更新DI信号状态
		/// </summary>
		public bool UpdateDISignalState(DISignalId id, bool state)
		{
			try
			{
				string signalId = IOSignalUtils.GetDISignalName(id);
				if (_diSignals.TryGetValue(signalId, out var signal))
				{
					signal.State = state;
					return true;
				}

				_logger.LogWarning($"更新失败：未找到DI信号 {id}");
				return false;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"更新DI信号 {id} 状态异常");
				return false;
			}
		}

		/// <summary>
		/// 批量更新DI信号状态
		/// </summary>
		public int UpdateDISignalStates(int states)
		{
			int updatedCount = 0;

			foreach (DISignalId id in Enum.GetValues(typeof(DISignalId)))
			{
				int bitMask = IOSignalUtils.GetDIBitMask(id);
				bool state = (states & bitMask) != 0;

				if (UpdateDISignalState(id, state))
				{
					updatedCount++;
				}
			}

			return updatedCount;
		}

		/// <summary>
		/// 批量更新DO信号状态
		/// </summary>
		public int UpdateDOSignalStates(int states)
		{
			int updatedCount = 0;

			foreach (DOSignalId id in Enum.GetValues(typeof(DOSignalId)))
			{
				try
				{
					string signalId = IOSignalUtils.GetDOSignalName(id);
					if (_doSignals.TryGetValue(signalId, out var signal))
					{
						int bitMask = IOSignalUtils.GetDOBitMask(id);
						bool state = (states & bitMask) != 0;

						signal.State = state; // 只更新内部状态，不发送到硬件
						updatedCount++;
					}
				}
				catch (Exception ex)
				{
					_logger.LogError(ex, $"更新DO信号 {id} 状态异常");
				}
			}

			return updatedCount;
		}

		/// <summary>
		/// 更新AI信号值
		/// </summary>
		public bool UpdateAISignalValue(AISignalId id, double value)
		{
			try
			{
				string signalId = IOSignalUtils.GetAISignalName(id);
				if (_aiSignals.TryGetValue(signalId, out var signal))
				{
					signal.Value = value;
					return true;
				}

				_logger.LogWarning($"更新失败：未找到AI信号 {id}");
				return false;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"更新AI信号 {id} 值异常");
				return false;
			}
		}

		/// <summary>
		/// 设置DO信号状态
		/// </summary>
		public async Task<bool> SetDOSignalStateAsync(DOSignalId id, bool state)
		{
			try
			{
				string signalId = IOSignalUtils.GetDOSignalName(id);
				if (_doSignals.TryGetValue(signalId, out var signal))
				{
					return await signal.SetStateAsync(state);
				}

				_logger.LogWarning($"设置失败：未找到DO信号 {id}");
				return false;
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, $"设置DO信号 {id} 状态异常");
				return false;
			}
		}

		/// <summary>
		/// 设置多个DO信号状态
		/// </summary>
		public async Task<int> SetDOSignalStatesAsync(Dictionary<DOSignalId, bool> signals)
		{
			if (signals == null || signals.Count == 0)
			{
				return 0;
			}

			int successCount = 0;
			foreach (var signal in signals)
			{
				if (await SetDOSignalStateAsync(signal.Key, signal.Value))
				{
					successCount++;
				}
			}

			return successCount;
		}

		/// <summary>
		/// 信号状态变化事件处理
		/// </summary>
		private void OnSignalStateChanged(object sender, IOSignalStateChangedEventArgs e)
		{
			try
			{
				SignalStateChanged?.Invoke(this, e);
			}
			catch (Exception ex)
			{
				_logger.LogError(ex, "处理信号状态变化事件异常");
			}
		}
	}
}